<script setup>
import * as THREE from "three";
import {
  AdditiveBlending,
  AmbientLight, BufferAttribute, BufferGeometry, Color,
  DirectionalLight, Float32BufferAttribute,
  HemisphereLight, LineBasicMaterial, LineSegments, Mesh, MeshLambertMaterial, Object3D,
  PCFShadowMap,
  PerspectiveCamera,
  PointLight, Points, PointsMaterial, SphereGeometry, Sprite, SpriteMaterial, TextureLoader, Vector3,
  WebGLRenderer
} from "three";
import {CSS2DRenderer} from "three/addons";
import starPng from '@/assets/images/starBg.png'
import earthTexture from '@/assets/images/world.topo.bathy.200401.jpg'

import pointArr from "./world";
import TWEEN from "@tweenjs/tween.js";

const webgl = ref()
// import { countryLineColor } from "../config/index";
class GlobalConfig {
  static earthRadius = 14
  // private static globalConfig:GlobalConfig
  // private constructor() {
  // }
  // private static shared(){
  //   if (this.globalConfig === null) {
  //   }
  // }
}
class View {
  constructor({
    canvas,
    width,
    height,
    cameraPosition,
    fieldOfView = 50,
  }){
    this.width = width || window.innerWidth;
    this.height = height || window.innerHeight;
    this.aspectRatio = this.width / this.height;
    this.camera = new PerspectiveCamera(
        fieldOfView,
        this.aspectRatio
    );
    this.earthRadius = 14
    this.countryLineColor = 0x7aa5a5
    this.controlConfig = {
      minZoom: 0.5,
      maxZoom: 2,
      minPolarAngle: 0,
      maxPolarAngle: Math.PI / 2,
    };
    let object3D = new Object3D();
    let earthMesh = this.createEarthImageMesh(this.earthRadius);
  }
  initRender() {
    let renderer = new WebGLRenderer({
      antialias: true,
      alpha: true
    });
    renderer.shadowMap.enabled = false;
    renderer.shadowMap.type = PCFShadowMap;
    renderer.setSize(this.width,this.height)

    return renderer
  }
  initRender2D(){
    const renderer2d = new CSS2DRenderer();
    renderer2d.setSize(this.width,this.height)
    renderer2d.domElement.style.position = "absolute";
    renderer2d.domElement.style.top = "0px";
    renderer2d.domElement.tabIndex = 0;
    renderer2d.domElement.className = "coreInnerRenderer2d";
    return renderer2d
  }
  initLight(scene){
    /**
     * 光源设置
     */
        // 平行光
    const directionalLight = new DirectionalLight(0x80b5ff, 1);
    directionalLight.position.set(-250, 250, 100);
    scene.add(directionalLight);

    // 点光
    const pointLight = new PointLight(0x80d4ff, 1);
    pointLight.position.set(-250, 250, 100);
    scene.add(pointLight);

    // 半球光
    const hemisphereLight = new HemisphereLight(0xffffff, 0x3d6399, 1);
    hemisphereLight.position.set(-250, 250, 100);
    scene.add(hemisphereLight);

    //环境光
    const ambient = new AmbientLight(0x002bff, 0.8);
    scene.add(ambient);
  }
  starBackground() {
    const positions = [];
    const colors = [];
    const geometry = new BufferGeometry();
    for (var i = 0; i < 10000; i++) {
      var vertex = new Vector3();
      vertex.x = Math.random() * 2 - 1;
      vertex.y = Math.random() * 2 - 1;
      vertex.z = Math.random() * 2 - 1;
      positions.push(vertex.x, vertex.y, vertex.z);
      var color = new Color();
      color.setHSL(Math.random() * 0.2 + 0.5, 0.55, Math.random() * 0.25 + 0.55);
      colors.push(color.r, color.g, color.b);
    }
    geometry.setAttribute("position", new Float32BufferAttribute(positions, 3));
    geometry.setAttribute("color", new Float32BufferAttribute(colors, 3));

    var textureLoader = new TextureLoader();
    var texture = textureLoader.load(starPng); //加载纹理贴图

    var starsMaterial = new PointsMaterial({
      map: texture,
      size: 1,
      transparent: true,
      opacity: 1,
      vertexColors: true, //true：且该几何体的colors属性有值，则该粒子会舍弃第一个属性--color，而应用该几何体的colors属性的颜色
      blending: AdditiveBlending,
      sizeAttenuation: true,
    });
    let stars = new Points(geometry, starsMaterial);
    stars.scale.set(300, 300, 300);

    return stars
  }
  createEarthImageMesh(radius) {
    // TextureLoader创建一个纹理加载器对象，可以加载图片作为纹理贴图
    const textureLoader = new TextureLoader();
    //加载纹理贴图
    const texture = textureLoader.load(earthTexture);
    //创建一个球体几何对象
    const geometry = new SphereGeometry(radius, 96, 96);
    //材质对象Material
    // MeshLambertMaterial  MeshBasicMaterial
    const material = new MeshLambertMaterial({
      map: texture, //设置地球0颜色贴图map
    });
    return new Mesh(geometry, material); //网格模型对象Mesh
  };
  countryLine(R) {
    var geometry = new BufferGeometry(); //创建一个Buffer类型几何体对象
    //类型数组创建顶点数据
    var vertices = new Float32Array(pointArr);
    // 创建属性缓冲区对象
    var attribute = new BufferAttribute(vertices, 3); //3个为一组，表示一个顶点的xyz坐标
    // 设置几何体attributes属性的位置属性
    geometry.attributes.position = attribute;
    // 线条渲染几何体顶点数据
    var material = new LineBasicMaterial({
      color: this.countryLineColor, //线条颜色
    }); //材质对象
    var line = new LineSegments(geometry, material); //间隔绘制直线
    line.scale.set(R, R, R); //lineData.js对应球面半径是1，需要缩放R倍
    return line;
  }
  earthGlow(radius,img,scale){
    // TextureLoader创建一个纹理加载器对象，可以加载图片作为纹理贴图
    var textureLoader = new TextureLoader();
    var texture = textureLoader.load(img); //加载纹理贴图
    // 创建精灵材质对象SpriteMaterial
    var spriteMaterial = new SpriteMaterial({
      map: texture, //设置精灵纹理贴图
      transparent: true, //开启透明
      // opacity: 0.5,//可以通过透明度整体调节光圈
    });
    // 创建表示地球光圈的精灵模型
    var sprite = new Sprite(spriteMaterial);
    sprite.scale.set(radius * scale, radius * scale, 1); //适当缩放精灵

    return sprite
  };
  animate = () => {
    if (this.waveMeshArr) {
      cityWaveAnimate(this.waveMeshArr);
    }
    requestAnimationFrame(this.animate);
    //只是自转，不需要缩放到中国
    if (this.earth3dObj) {
      if (this.earthConfig.autoRotate && !this.earthConfig.zoomChina) {
        this.earth3dObj.rotation.y += 0.01;
      }
    }
    this.renderer.render(this.scene, this.camera);
    this.afterAnimate();
  };

  afterAnimate = () => {
    TWEEN.update();
    //飞线更新，这句话一定要有
    if (this.flyManager != null) {
      this.flyManager.animation();
    }
  };
}

onMounted(() => {
  nextTick(() => {
    webgl.value.width = window.innerWidth;
    webgl.value.height = window.innerHeight;
    const view = new View({
      canvas: webgl.value,
      width:  webgl.value.width,
      height: webgl.value.height,
      cameraPosition: { x: 0, y: 2, z: 14 }
    })
  })
})
</script>

<template>
  <canvas ref="webgl"></canvas>
</template>

<style scoped lang="scss">

</style>